package store.lunangangster.nodeflow.util;

import cn.hutool.core.collection.CollUtil;
import store.lunangangster.nodeflow.core.component.NodeComponent;
import store.lunangangster.nodeflow.exception.UnknownExecutableException;
import store.lunangangster.nodeflow.rt.element.Chain;
import store.lunangangster.nodeflow.rt.element.Executable;
import store.lunangangster.nodeflow.rt.element.Node;
import store.lunangangster.nodeflow.rt.element.flow.Flow;

/**
 * {@link Executable}的相关工具类
 *
 * @author cwk
 * @version 1.0
 */
public class ExecutableUtil {

	/**
	 * 判断当前可执行对象是否为空
	 * <ul>
	 *   <li>若可执行对象为null则返回true</li>
	 *   <li>针对{@link Node}，判断其对象是否为空或其包含的{@link NodeComponent}对象为空</li>
	 *   <li>针对{@link Chain}，判断其对象为空或者其对应的执行流{@link Flow}集合为空</li>
	 *   <li>针对{@link Flow}，判断其包含的每一个{@link Executable}对象是否为空（通过当前方法），只要有一个不为空则部位空</li>
	 * </ul>
	 * @param executable	待判断的可执行对象
	 * @return						当可执行对象为空时返回true，为空的判断如上述描述
	 */
	public static boolean isEmpty(Executable executable) {
		if (executable == null) {
			return true;
		}
		if (executable instanceof Node) {
			return isEmptyNode((Node) executable);
		}
		if (executable instanceof Chain) {
			return isEmptyChain((Chain) executable);
		}
		if (executable instanceof Flow) {
			return isEmptyFlow((Flow) executable);
		}
		throw new UnknownExecutableException("Unknown executable item: " + executable.getClass());
	}

	private static boolean isEmptyNode(Node node) {
		return node == null || node.getNodeComponent() == null;
	}

	private static boolean isEmptyChain(Chain chain) {
		if (chain == null || CollUtil.isEmpty(chain.getFlowList())) {
			return true;
		}
		for (Flow flow : chain.getFlowList()) {
			if (isEmptyFlow(flow)) {
				return true;
			}
		}
		return false;
	}

	private static boolean isEmptyFlow(Flow flow) {
		if (flow == null || CollUtil.isEmpty(flow.getExecutableList())) {
			return true;
		}
		for (Executable executable : flow.getExecutableList()) {
			if (!isEmpty(executable)) {
				return false;
			}
		}
		return true;
	}
}
